using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using Horizon;

namespace HorizonTestClient
{
    public partial class UserInfoForm : Form
    {
        private Patron selectedPatronValue;

        public UserInfoForm()
        {
            InitializeComponent();

            holdingsDataGridView.AutoGenerateColumns = false;
            AddHoldingsColumn("Author", "Author");
            AddHoldingsColumn("Title", "Title");
            AddHoldingsColumn("Format", "Format");
            AddHoldingsColumn("Checked Out", "CheckOutDate");
            AddHoldingsColumn("Due", "DueDate");
            AddHoldingsColumn("Reason", "BlockReason");
            AddHoldingsColumn("Amount", "Amount");
        }

        /// <summary>
        /// Patron being managed by this dialog
        /// </summary>
        public Patron SelectedPatron
        {
            get { return selectedPatronValue; }
            set
            {
                selectedPatronValue = value;
            }
        }

        /// <summary>
        /// Update DataGridView to show items checked out
        /// </summary>
        public void DisplayHoldings()
        {
            holdingsDataGridView.DataSource = null;
            holdingsDataGridView.DataSource = selectedPatronValue.ItemsOut;
        }

        /// <summary>
        /// Update DataGridView to show blocks
        /// </summary>
        public void DisplayBlocks()
        {
            holdingsDataGridView.DataSource = null;
            holdingsDataGridView.DataSource = selectedPatronValue.Blocks;
        }

        /// <summary>
        /// Update DataGridView to show holds
        /// </summary>
        public void DisplayHolds()
        {
            holdingsDataGridView.DataSource = null;
            holdingsDataGridView.DataSource = selectedPatronValue.Holds;
        }

        /// <summary>
        /// Utility method to add columns to DataGridView
        /// </summary>
        /// <param name="name">Display name for this new column</param>
        /// <param name="dataProperty">Databound property for this column</param>
        private void AddHoldingsColumn(string name, string dataProperty)
        {
            DataGridViewTextBoxColumn c = new DataGridViewTextBoxColumn();
            c.Name = name;
            c.HeaderText = name;
            c.DataPropertyName = dataProperty;
            c.SortMode = DataGridViewColumnSortMode.Automatic;

            holdingsDataGridView.Columns.Add(c);
        }

        /// <summary>
        /// Invoked user clicks "Details" for holdings
        /// </summary>
        private void booksOutDetailsButton_Click(object sender, EventArgs e)
        {
            DisplayHoldings();
        }

        /// <summary>
        /// Invoked user clicks "Details" for blocks (fines)
        /// </summary>
        private void finesDetailsButton_Click(object sender, EventArgs e)
        {
            DisplayBlocks();
        }

        /// <summary>
        /// Updates UI fields based on selected patron object
        /// </summary>
        private void UpdateFields()
        {
            if (selectedPatronValue == null)
            {
                barcodeTextBox.Text = "";
                pinTextBox.Text = "";

                userNameTextBox.Text = "";
                userEmailTextBox.Text = "";
                userAddressTextBox.Text = "";
                userPatronIdTextBox.Text = "";
                userPhoneTextBox.Text = "";

                finesDueTextBox.Text = "";
                booksOutTextBox.Text = "";
                booksOverdueTextBox.Text = "";
            }
            else
            {
                barcodeTextBox.Text = selectedPatronValue.BarCode;
                pinTextBox.Text = selectedPatronValue.Password;

                userNameTextBox.Text = selectedPatronValue.Name;
                userEmailTextBox.Text = selectedPatronValue.EmailAddress;
                userAddressTextBox.Text = selectedPatronValue.Address;
                userPatronIdTextBox.Text = selectedPatronValue.PatronId;
                userPhoneTextBox.Text = selectedPatronValue.Phone;

                finesDueTextBox.Text = selectedPatronValue.TotalFines;
                booksOutTextBox.Text = selectedPatronValue.ItemsOut.Count.ToString();
                booksOverdueTextBox.Text = selectedPatronValue.ItemsOverdueCount.ToString();
                holdsCountTextBox.Text = selectedPatronValue.Holds.Count.ToString();
            }

            DisplayHoldings();
        }

        /// <summary>
        /// Unmasks password/PIN when user enters the text box
        /// </summary>
        private void pinTextBox_Enter(object sender, EventArgs e)
        {
            pinTextBox.UseSystemPasswordChar = false;
        }

        /// <summary>
        /// Masks password/PIN when user leaves the text box
        /// </summary>
        private void pinTextBox_Leave(object sender, EventArgs e)
        {
            pinTextBox.UseSystemPasswordChar = true;
        }

        /// <summary>
        /// Logs in/updates patron details and alerts for overdue items
        /// </summary>
        private void dialogAcceptButton_Click(object sender, EventArgs e)
        {

            if (!string.IsNullOrEmpty(barcodeTextBox.Text))
            {
                // Set aside patron bar code/pin in case login fails
                string user, password;
                user = selectedPatronValue.BarCode;
                password = selectedPatronValue.Password;

                // Update user login info based on text boxes
                selectedPatronValue.BarCode = barcodeTextBox.Text;
                selectedPatronValue.Password = pinTextBox.Text;

                try
                {
                    // Confirm credentials if changed
                    if (user != selectedPatronValue.BarCode || password != selectedPatronValue.Password)
                    {
                        // First invalidate the session in case the user was logged in and new password is wrong
                        selectedPatronValue.CurrentSession.Invalidate();
                        selectedPatronValue.CurrentSession.SessionLibrary.ReadPatronDetails(selectedPatronValue);

                        UpdateFields();
                    }

                    this.DialogResult = DialogResult.OK;
                    this.Close();
                }
                catch (Exception ex)
                {
                    // Login failed -- revert bar code/pin
                    selectedPatronValue.BarCode = user;
                    selectedPatronValue.Password = password;

                    MessageBox.Show("An error occured.  Please check your login information: " + ex.Message);
                }
            }
        }

        /// <summary>
        /// Formats overdue cells with red background
        /// </summary>
        private void holdingsDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            // Don't format blocks list
            if (holdingsDataGridView.DataSource != selectedPatronValue.Blocks)
            {
                Holding h = (Holding)(holdingsDataGridView.Rows[e.RowIndex].DataBoundItem);
                if (h != null)
                {
                    TimeSpan ts = DateTime.Parse(h.DueDate).Subtract(DateTime.Now.Date);

                    if (ts.Days < 1)
                        e.CellStyle.BackColor = Color.Red;
                    else if (ts.Days < 3)
                        e.CellStyle.BackColor = Color.Yellow;
                }
            }
        }

        /// <summary>
        /// Hides password and updates fields when form is shown
        /// </summary>
        private void UserInfoForm_Shown(object sender, EventArgs e)
        {
            pinTextBox.UseSystemPasswordChar = true;
            UpdateFields();
            barcodeTextBox.Focus();
        }

        /// <summary>
        /// Invoked when user clicks "Details" to see holds
        /// </summary>
        private void holdsDetailsButton_Click(object sender, EventArgs e)
        {
            DisplayHolds();
        }
   }
}